package com.starview.star.operators.assignment.runtime;

import com.starview.platform.data.EvaluationException;
import com.starview.platform.data.IFunction;
import com.starview.platform.data.IValue;
import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.Refresher;
import com.starview.platform.data.type.StandardTypes;
import com.starview.platform.data.type.TypeUtils;
import com.starview.platform.data.value.Factory;
import com.starview.star.operators.CafeEnter;
import com.starview.star.operators.assignment.runtime.AtomicInt.AtomIntCell;

public class AtomicIntOps
{
  private static final IType rawIntType = StandardTypes.rawIntegerType;

  public static class AtomIntReference implements IFunction
  {
    public static final String name = "__atomic_int_reference";

    @CafeEnter
    public static int enter(AtomIntCell cell)
    {
      return cell.get();
    }

    @Override
    public IValue enter(IValue... args)
    {
      return Factory.newInt(enter((AtomIntCell) args[0]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      return Refresher.generalize(TypeUtils.functionType(AtomicInt.type, StandardTypes.rawIntegerType));
    }
  }

  public static class AtomIntAssignment implements IFunction
  {
    public static final String name = "__atomic_int_assign";

    @CafeEnter
    public static IValue enter(AtomIntCell cell, int value)
    {
      cell.set(value);
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((AtomIntCell) args[0], Factory.intValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      return Refresher.generalize(TypeUtils.procedureType(AtomicInt.type, rawIntType));
    }
  }

  public static class AtomIntTestAndSet implements IFunction
  {
    public static final String name = "__atomic_int_test_n_set";

    @CafeEnter
    public static IValue enter(AtomIntCell cell, int expected, int actual)
    {
      return Factory.newBool(cell.compareAndSet(expected, actual));
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((AtomIntCell) args[0], Factory.intValue(args[1]), Factory.intValue(args[2]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      return Refresher.generalize(TypeUtils.functionType(AtomicInt.type, rawIntType, rawIntType,
          StandardTypes.booleanType));
    }
  }
}
